/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package com.ztesoft.zcm.cmdb.util.remote;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.ztesoft.zsmart.core.exception.BaseAppException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 *
 */
public abstract class RemoteClient {
    protected static final ExecutorService pool = new ThreadPoolExecutor(0,
            200,
            300L,
            TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(),
            new BasicThreadFactory.Builder().namingPattern("exec-waiting-pool-%s").daemon(true).build());

    private HostAccessInfo hostAccessInfo;
    public RemoteClient(HostAccessInfo hostAccessInfo) {
        this.hostAccessInfo = hostAccessInfo;
    }
    public HostAccessInfo getHostAccessInfo() {
        return this.hostAccessInfo;
    }

    /**
     * Open an ssh session.
     * @return the opened session
     * @throws JSchException on error
     */
    protected Session openSession() throws JSchException {
        JSch jsch = new JSch();
        if (StringUtils.isNotEmpty(hostAccessInfo.getKeyfile())) {
            jsch.addIdentity(hostAccessInfo.getKeyfile());
        }

        Session session = jsch.getSession(hostAccessInfo.getUser(), hostAccessInfo.getHost(), hostAccessInfo.getPort());
        session.setPassword(hostAccessInfo.getPassword());
        session.setConfig("StrictHostKeyChecking", "no");
        session.setConfig("PreferredAuthentications", "publickey,password");
        session.setUserInfo(hostAccessInfo);
        session.connect(hostAccessInfo.getConnTimeout() * 1000);
        return session;
    }

    /**
     * 关闭远程客户端连接
     */
    public abstract  void close();

    /**
     * 在远程主机执行命令
     *
     * @param cmd
     * @param patterns 期望的命令输出满足的正则表达式
     * @return
     */
    public abstract  RemoteResult exec(String cmd, String... patterns) throws BaseAppException;

    /**
     * 在远程主机执行命令
     *
     * @param cmd
     * @param timeout  命令执行超时时间
     * @param patterns 期望的命令输出满足的正则表达式
     * @return
     */
    public abstract  RemoteResult exec(String cmd, int timeout, String... patterns) throws BaseAppException;
}
